package pv.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.MediaStore;

public class ImageHelper {
	private static ImageHelper instance = new ImageHelper();

	// private final Map<String, Drawable> drawableMap;
	private static int MAX_IMAGE_DIMENSION = 720;

	Drawable image;

	public synchronized static ImageHelper getInstance() {
		return instance;
	}

	private ImageHelper() {
		// drawableMap = new HashMap<String, Drawable>();
	}

	public Drawable fetchDrawable(String urlString) {

		try {
			InputStream is = fetch(urlString);
			Drawable drawable = Drawable.createFromStream(is, "src");
			return drawable;
		} catch (MalformedURLException e) {
			Utility.LogE(this.getClass(), e);

			return null;
		} catch (IOException e) {
			Utility.LogE(this.getClass(), e);
			return null;
		} catch (OutOfMemoryError e) {
			// TODO: handle exception
			Utility.LogM(this.getClass(), e.getMessage());
			return null;
		}
	}

	public static int getOrientation(Context context, Uri photoUri) {
		/* it's on the external media. */
		Cursor cursor = context.getContentResolver().query(photoUri,
				new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
				null, null, null);

		if (cursor.getCount() != 1) {
			return -1;
		}

		cursor.moveToFirst();
		int orientation = cursor.getInt(0);
		cursor.close();

		return orientation;
	}

	public byte[] convertBitmapToByteArray(Bitmap bm) {
		// ByteArrayOutputStream stream = new ByteArrayOutputStream();
		// bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
		// return stream.toByteArray();

		float rotatedWidth = bm.getWidth();
		float rotatedHeight = bm.getHeight();

		if (rotatedWidth > MAX_IMAGE_DIMENSION
				|| rotatedHeight > MAX_IMAGE_DIMENSION) {
			float widthRatio = ((float) rotatedWidth)
					/ ((float) MAX_IMAGE_DIMENSION);
			float heightRatio = ((float) rotatedHeight)
					/ ((float) MAX_IMAGE_DIMENSION);
			float maxRatio = Math.max(widthRatio, heightRatio);

			// Create the bitmap from file
			// BitmapFactory.Options options = new BitmapFactory.Options();
			// options.inSampleSize = (int) maxRatio;
			// Bitmap.srcBitmap = BitmapFactory.decodeStream(is, null, options);
			bm = Bitmap.createScaledBitmap(bm, (int) (rotatedWidth / maxRatio),
					(int) (rotatedHeight / maxRatio), true);
		}
		byte[] bMapArray = null;
		try {

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
			bMapArray = baos.toByteArray();
			baos.close();
		} catch (IOException e) {
			// TODO: handle exception
			Utility.LogE(this.getClass(), e);
		}
		return bMapArray;
	}

	public Bitmap convertToBimap(Context context, Uri photoUri)
			throws IOException {
		InputStream is = context.getContentResolver().openInputStream(photoUri);
		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(is, null, dbo);
		is.close();

		int rotatedWidth, rotatedHeight;
		int orientation = getOrientation(context, photoUri);

		if (orientation == 90 || orientation == 270) {
			rotatedWidth = dbo.outHeight;
			rotatedHeight = dbo.outWidth;
		} else {
			rotatedWidth = dbo.outWidth;
			rotatedHeight = dbo.outHeight;
		}

		Bitmap srcBitmap;
		is = context.getContentResolver().openInputStream(photoUri);
		if (rotatedWidth > MAX_IMAGE_DIMENSION
				|| rotatedHeight > MAX_IMAGE_DIMENSION) {
			float widthRatio = ((float) rotatedWidth)
					/ ((float) MAX_IMAGE_DIMENSION);
			float heightRatio = ((float) rotatedHeight)
					/ ((float) MAX_IMAGE_DIMENSION);
			float maxRatio = Math.max(widthRatio, heightRatio);

			// Create the bitmap from file
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inSampleSize = (int) maxRatio;
			srcBitmap = BitmapFactory.decodeStream(is, null, options);
		} else {
			srcBitmap = BitmapFactory.decodeStream(is);
		}
		is.close();

		/*
		 * if the orientation is not 0 (or -1, which means we don't know), we
		 * have to do a rotation.
		 */
		if (orientation > 0) {
			Matrix matrix = new Matrix();
			matrix.postRotate(orientation);

			srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
					srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
		}

		// String type = context.getContentResolver().getType(photoUri);
		// ByteArrayOutputStream baos = new ByteArrayOutputStream();
		// if (type.equals("image/png")) {
		// srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
		// } else if (type.equals("image/jpg") || type.equals("image/jpeg")) {
		// srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
		// }
		// byte[] bMapArray = baos.toByteArray();
		// baos.close();
		return srcBitmap;

	}

	public Bitmap scaleImage(int w, int h, Bitmap bm) {
		Bitmap result = null;
		try {

			result = bm.createScaledBitmap(bm, w, h, true);
		} catch (Exception e) {
			// TODO: handle exception
			Utility.LogE(this.getClass(), e);
		}

		return result;

	}

	public byte[] scaleImage(Context context, Uri photoUri) throws IOException {
		InputStream is = context.getContentResolver().openInputStream(photoUri);
		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(is, null, dbo);
		is.close();

		int rotatedWidth, rotatedHeight;
		int orientation = getOrientation(context, photoUri);

		if (orientation == 90 || orientation == 270) {
			rotatedWidth = dbo.outHeight;
			rotatedHeight = dbo.outWidth;
		} else {
			rotatedWidth = dbo.outWidth;
			rotatedHeight = dbo.outHeight;
		}

		Bitmap srcBitmap;
		is = context.getContentResolver().openInputStream(photoUri);
		if (rotatedWidth > MAX_IMAGE_DIMENSION
				|| rotatedHeight > MAX_IMAGE_DIMENSION) {
			float widthRatio = ((float) rotatedWidth)
					/ ((float) MAX_IMAGE_DIMENSION);
			float heightRatio = ((float) rotatedHeight)
					/ ((float) MAX_IMAGE_DIMENSION);
			float maxRatio = Math.max(widthRatio, heightRatio);

			// Create the bitmap from file
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inSampleSize = (int) maxRatio;
			srcBitmap = BitmapFactory.decodeStream(is, null, options);
		} else {
			srcBitmap = BitmapFactory.decodeStream(is);
		}
		is.close();

		/*
		 * if the orientation is not 0 (or -1, which means we don't know), we
		 * have to do a rotation.
		 */
		if (orientation > 0) {
			Matrix matrix = new Matrix();
			matrix.postRotate(orientation);

			srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
					srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
		}

		String type = context.getContentResolver().getType(photoUri);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		if (type.equals("image/png")) {
			srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
		} else if (type.equals("image/jpg") || type.equals("image/jpeg")) {
			srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
		}
		byte[] bMapArray = baos.toByteArray();
		baos.close();
		return bMapArray;
	}

	public void fetchDrawableOnThread(String url, Drawable image) {
		this.image = image;
	}

	public Bitmap boderForImage(Context context, Bitmap source, int newHeight,
			int newWidth, int border, int colorID) {

		try {

			int sourceWidth = source.getWidth();
			int sourceHeight = source.getHeight();

			// Compute the scaling factors to fit the new height and width,
			// respectively.
			// To cover the final image, the final scaling will be the bigger
			// of these two.
			float xScale = (float) newWidth / sourceWidth;
			float scale = Math.max(xScale, xScale);

			// Now get the size of the source bitmap when scaled
			float scaledWidth = scale * sourceWidth;
			float scaledHeight = scale * sourceHeight;

			// Let's find out the upper left coordinates if the scaled bitmap
			// should be centered in the new size give by the parameters
			float left = (newWidth - scaledWidth) / 2;
			float top = (newHeight - scaledHeight) / 2;

			// The target rectangle for the new, scaled version of the source
			// bitmap will now
			// be
			RectF targetRect = new RectF(left + border, top + border, left
					+ scaledWidth, top + scaledHeight);
			Bitmap dest = Bitmap.createBitmap(newWidth + border, newHeight
					+ border, source.getConfig());
			Canvas canvas = new Canvas(dest);
			canvas.drawColor(colorID);
			canvas.drawBitmap(source, null, targetRect, null);

			return dest;

		} catch (Exception e) {
			Utility.LogE(this.getClass(), e);
		}

		return null;
	}

	private InputStream fetch(String urlString) throws MalformedURLException,
			IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpGet request = new HttpGet(urlString);
		HttpResponse response = httpClient.execute(request);
		return response.getEntity().getContent();
	}
}
